home *** CD-ROM | disk | FTP | other *** search
- /*
- * path.c - routines for manipulating Mac file paths
- * and RevRdist file_info structures.
- */
-
- #include "RevRdist.h"
-
- extern void lastpart (StringPtr);
-
-
-
- /*
- *=========================================================================
- * freeInfo (fi) - zap contents of file_info structure
- * entry: fi = pointer to structure
- *=========================================================================
- */
-
- void
- freeInfo (fi)
- file_info_t * fi;
- {
- if (fi->f_path)
- DisposHandle ((Handle) fi->f_path);
- ZEROAT (fi);
- }
-
-
- /*
- *=========================================================================
- * fullpath (path, vRefNum, dirID) - construct absolute path
- * entry: path = input partial path
- * vRefNum = volume or working directory path is relative to
- * dirID = parent id of path
- * can be 0 if path and vRefNum are from standard file
- * returns: path, edited in place
- * path is the empty string on error
- *=========================================================================
- */
- StringPtr
- fullpath (path, vRefNum, dirID)
- StringPtr path;
- Integer vRefNum;
- Longint dirID;
- {
- OSErr result;
- Size len; /* string lengths */
- int offset; /* offset of first in-use char in tname */
- CInfoPBRec ci;
- Str255 dname; /* path component name */
- Str255 tname; /* temp space */
- #define dp ci.dirInfo
-
- offset = sizeof(tname);
- len = path[0];
- if (len == 0)
- return;
- /*
- * Find the folder containing the supplied file/folder
- */
- ZERO(ci);
- ci.hFileInfo.ioNamePtr = path;
- ci.hFileInfo.ioVRefNum = vRefNum;
- ci.hFileInfo.ioDirID = dirID;
- result = PBGetCatInfo(&ci, FALSE);
-
- dp.ioNamePtr = dname;
- COPYPS (path, dname);
- lastpart (dname);
- path[0] = 0;
- if (result == noErr)
- {
- if (ci.hFileInfo.ioFlAttrib & 0x10)
- tname[--offset] = ':'; /* trailing colon on folder names */
- for (;;)
- {
- /*
- * Insert current component (in dname) into tname
- */
- len = dname[0];
- offset -= len;
- if (offset <= 0)
- return;
- BlockMove (dname+1, tname+offset, len);
- tname[--offset] = ':';
- /*
- * Look up its parent
- */
- if (dp.ioDrDirID == ROOTDIRID)
- break;
- dp.ioDrDirID = dp.ioDrParID;
- dp.ioDrParID = 0;
- dp.ioFDirIndex = -1;
- dname[0] = '\0';
- if (result = PBGetCatInfo(&ci,0))
- return;
- }
- len = sizeof(tname) - offset; /* includes length byte */
- tname[offset] = len - 1;
- BlockMove (&tname[offset], path, len);
- }
- return path;
- }
-
-
-
-
- /*
- *=========================================================================
- * getInfoByPath (path, fi) - fill in file_list structure from file path
- * entry: path = full or partial path name
- * fi = pointer to (possibly) partially filled in file_list struct
- * If fi->f_ref is set, then it and fi->f_info.ctype identify
- * file/folder.
- * Otherwise, path and fi->f_vol identify it (these could be set
- * from Standard File).
- * returns: 0 if no errors, all of fi now set
- * else OSErr, fi possibly modified
- *=========================================================================
- */
- OSErr
- getInfoByPath (path, fi)
- StringPtr path;
- file_info_t * fi;
- {
- cnode_t * cn; /* points to f_info in fi */
- ctype_t ct; /* are we working on a file or folder */
- Longint dirID; /* file/folder directory id */
- OSErr error;
- Integer idx; /* for indexing through folder */
- Longint parID; /* parent ID */
- StringHandle sh; /* temp ptr to full path name */
- Integer vol; /* volume reference number */
- CInfoPBRec ci;
- FCBPBRec fcb;
- HParamBlockRec pb;
- WDPBRec wd;
- Str255 s;
-
- cn = &fi->f_info;
- COPYPS (path, s);
- /*
- * Collect enough information for a PBGetCatInfo call.
- *
- * If we have a reference number,
- * If it is for a folder, the reference is a working directory ref number,
- * use it to get the volume and directory id.
- * Otherwise, it is for a file. Use PBGetFCBInfo to get file's volume,
- * parent ID, and file number.
- * If we don't have a reference number, then path and (possibly zero) vol
- * have to suffice. However, in this case, use PBHGetVInfo to get
- * volume.
- */
- if (fi->f_ref)
- {
- if ((ct = cn->ctype) == C_FOLDER)
- {
- ZERO (wd);
- wd.ioVRefNum = fi->f_ref;
- wd.ioWDIndex = 0;
- if (error = PBGetWDInfo (&wd, false))
- return error;
- vol = wd.ioWDVRefNum;
- dirID = wd.ioWDDirID;
- parID = 0;
- }
- else
- {
- ZERO (fcb);
- fcb.ioRefNum = fi->f_ref;
- fcb.ioFCBIndx = 0;
- if (error = PBGetFCBInfo (&fcb, false))
- return error;
- vol = fcb.ioFCBVRefNum;
- dirID = fcb.ioFCBFlNm;
- parID = fcb.ioFCBParID;
- }
- }
- else
- {
- ZERO (ci);
- COPYPS (path, s);
- ci.hFileInfo.ioNamePtr = s;
- ci.hFileInfo.ioVRefNum = fi->f_vol;
- if (error = PBGetCatInfo (&ci, false))
- return error;
- ct = (ci.hFileInfo.ioFlAttrib & 0x10) ? C_FOLDER : C_FILE;
- dirID = ci.hFileInfo.ioDirID;
- parID = ci.hFileInfo.ioFlParID;
-
- vol = fi->f_vol;
- ZERO (pb);
- pb.volumeParam.ioNamePtr = s;
- pb.volumeParam.ioVRefNum = vol;
- pb.volumeParam.ioVolIndex = -1;
- if (error = PBHGetVInfo (&pb, false))
- return error;
- vol = pb.volumeParam.ioVRefNum;
- }
- /*
- * Finally, we have enough information to call PBGetCatInfo so that it
- * will return the file/folder name with correct capitalization.
- * For folders, a single call gets us what we want, but for files, we
- * must step through the parent directory until we get back the file
- * matching our dirID.
- */
- ZERO (ci);
- ci.hFileInfo.ioNamePtr = s;
- if (ct == C_FOLDER)
- {
- s[0] = 0;
- ci.dirInfo.ioVRefNum = vol;
- ci.dirInfo.ioDrDirID = dirID;
- ci.dirInfo.ioFDirIndex = -1;
- if (error = PBGetCatInfo (&ci, false))
- return error;
- parID = ci.dirInfo.ioDrParID;
- }
- else
- {
- for (idx = 1; ; idx++)
- {
- s[0] = 0;
- ci.hFileInfo.ioVRefNum = vol;
- ci.hFileInfo.ioFDirIndex = idx;
- ci.hFileInfo.ioDirID = parID;
- if (error = PBGetCatInfo (&ci, false))
- return error;
- if (ci.hFileInfo.ioDirID == dirID)
- break;
- }
- }
- /*
- * Whew! Finally have the info. Fill in fi.
- */
- saveCatInfo (&ci, cn);
- fi->f_vol = vol;
- fi->f_set = true;
- sh = fi->f_path;
- if (sh)
- DisposHandle ((Handle) sh);
- sh = 0;
- (void) fullpath (s, vol, parID);
- sh = (StringHandle) NewHandle ((Size) s[0] + 1);
- if (sh)
- COPYPS (s, *sh);
- else
- error = MemError ();
- fi->f_path = sh;
- return error;
- }
-
-
-
- /*
- *=========================================================================
- * lastpart(path) - given a path (absolute or partial), return its last
- * component.
- * entry: path = path string to examine.
- * returns: path = last part of path
- *=========================================================================
- */
- void
- lastpart (path)
- register StringPtr path;
- {
- register int i, len;
- int nexttolast, last; /* posns of colons in path */
-
- len = path[0];
- /*
- * Find the interesting colons
- */
- for (last = 0, i = 1; i <= len; i++)
- {
- if (path[i] == ':')
- {
- nexttolast = last;
- last = i;
- }
- }
- /*
- * If there are no colons, it's already as short as can be.
- */
- if (last == 0)
- return;
- /*
- * Ignore a final colon in deciding where to split
- */
- if (last == len)
- last = nexttolast;
- /*
- * Return from last+1 to the end.
- */
- len -= last;
- BlockMove (path+last+1, path+1, len);
- path[0] = len;
- return;
- }